#!/usr/bin/env python
# -*- coding: utf8 -*-

#-------------------------------------------------------------------------------
# Name:        module1
# Purpose:
#
# Author:      iori
#
# Created:     21/02/2014
# Copyright:   (c) iori 2014
# Licence:     <your licence>
#-------------------------------------------------------------------------------

# jd register

import json
import random
import time
import string
import requests
from pyquery import PyQuery
from PIL import Image
from StringIO import StringIO
import logging
import unittest
from utils import random_string

logging.basicConfig(filename='log.txt', level=logging.INFO,
                    format='%(asctime)s - %(name)s - %(levelname)s: %(message)s')


def get_vcode(data):
    img = Image.open(StringIO(data))
    img.show()
    authcode = raw_input("enter verify code: ")
    return authcode

class JD(object):
    def __init__(self, name, pwd, get_vcode=get_vcode):
        self.name = name
        self.pwd = pwd
        self.sn = requests.Session()
        self.get_vcode = get_vcode
        self.sn.headers = {'User-Agent':'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;; SIMBAR={E540A73C-FFAE-11E1-A7F7-002618241525})',
                                 'x-requested-with':'XMLHttpRequest',
                                 'Accept': 'application/json, text/javascript, */*; q=0.01',
                                 }
        self.status = self.login()

    def login(self):
        # login process
        url = 'https://passport.jd.com/new/login.aspx?ReturnUrl=http%3A%2F%2Fwww.jd.com%2F'
        jd = PyQuery(self.sn.get(url).text)
        unknow_fd = jd('div.coagent')('input')
        # check whether need verify code ?
        first_login = True
        while True:
            if first_login  and ('hide' in jd('div#o-authcode').attr['class']):
                # 不用验证码
                authcode = ''
                first_login = False
            else:
                vimg = jd('img#JD_Verification1')
                vurl = 'http:{}{}'.format(vimg.attr.onclick.split("'")[1], int(time.time()))
                authcode = get_vcode(self.sn.get(vurl).content)
            data = {'authcode': authcode,
                    'loginname': self.name,
                    'loginpwd': self.pwd,
                    'machineCpu': '',
                    'machineDisk': '',
                    'machineNet': '',
                    'nloginpwd': self.pwd,
                    unknow_fd.attr.name: unknow_fd.attr.value,
                    'uuid': jd('input[name=uuid]').attr.value}
            login_url = 'https://passport.jd.com/uc/loginService?uuid={}&ReturnUrl=http%3A%2F%2Fwww.jd.com%2F&r={}'.format(jd('input[name=uuid]').attr.value,random.random())
            # 登陆成功的响应是: ({"success":"http://www.jd.com/"})
            res = self.sn.post(url=login_url, data=data)
            print res.text
            res = json.loads(res.text[1:-1])
            if 'emptyAuthcode' not in res:
                break
        if 'success' in res:
            print 'login success'
        elif 'pwd' in res:
            print 'password wrong'
        return res

    def generate_vc(self):
        charset = string.digits + string.ascii_uppercase
        rs = random_string(20, charset)
        url = "http://captcha.jd.com/verify/image?srcid=yushou&is=337485efa478c837bdf2947c14c21687&acid={}".format(rs)
        return  rs, self.sn.get(url).content
    def subscribe(self, sku):
        ''' 预约商品，'''
        now = int(time.time())
        url = 'http://soa.yushou.jd.com/youshouinfo.action?sku=1043963&callback=jsonp{}&_={}'.format(now-500, now)
        res = self.sn.get(url).text
        s = res.find('(')
        res = json.loads(res[res.find('(')+1:res.rfind(')')])
        if res['type'] == '1':
            if res['url'] is None:
                print 'unable to subscribe'
            else:
                url = res['url']
                key = url[url.rfind('=')+1:]
                self.sn.get(res['url'])
                while True:
                    rs, data = self.generate_vc()
                    vcode = self.get_vcode(data)
                    url = 'http://yushou.jd.com/insideInvite/verifyCodeValidate.action?vkey={}&vvalue={}'.format(rs, vcode)
                    # {"pass_mark":false} {"pass_mark":true}
                    res = self.sn.post(url).json()
                    print res
                    if res['pass_mark'] == True:
                        break
                data = {'key': key,
                        'sku': sku,
                        'vkey': rs,
                        'vvalue': vcode}
                url = 'http://yushou.jd.com/yuyue.action'
                res = self.sn.post(url, data)
                jd = PyQuery(res.text)
                if jd('title').text() == u'预约成功':
                    print 'subscribe ok'

    def add_to_cart(self, sku):
        jd = PyQuery(self.sn.get('http://item.jd.com/{}.html'.format(sku)).text)
        link = jd('a#InitCartUrl')
        res = self.sn.get(link.attr.href).text
        title = PyQuery(res)('title').text()
        if u'成功加入' in title:
            print 'add to cart ok'

    def check_order(self, jd, ref):
        need = jd('div.mt').text()
        if u'核对订单信息' in need:
            # 填写地址信息，
            url = 'http://trade.jd.com/dynamic/consignee/editConsignee.action'
            jd = PyQuery(self.sn.post(url).text)
            info = jd('div#consignee-list').children('div').eq(0)
            data = {'consigneeParam.giftSendeConsigneeMobile': '',
                    'consigneeParam.giftSenderConsigneeName': '',
                    'consigneeParam.isUpdateCommonAddress': 1,
                    'consigneeParam.noteGiftSender': 'false',}
            builder = 'consigneeParam.{}'.format
            for item in info('input').items():
                name = item.attr.id.split('_')[2]
                data[builder(name)] = item.attr.value
            print data
            url = 'http://trade.jd.com/dynamic/consignee/saveConsignee.action'
            self.sn.headers['Referer'] = ref
            res = self.sn.post(url, data)
            print res.text
            res = res.json()
            print res
            if res['success']:
                url = 'http://trade.jd.com/dynamic/payAndShip/savePayAndShip.action'
                data = {'saveParam.otherShipmentType': 66,
                        'saveParam.paymentId': 4}
                res = self.sn.post(url, data)
    def submit_order(self):
        url = 'http://cart.jd.com/cart/cart.html?r={}'.format(int(time.time()))
        self.sn.get(url) # 查看购物车
        url = 'http://cart.jd.com/cart/dynamic/splitCart/splitCart.action?rd={}'.format(random.random())
        res = self.sn.get(url)
        jd = PyQuery(res.text)
        # 确定订单信息
        self.check_order(jd, res.url)
        track_id = jd('input#TrackID')
        # 基本的提交信息
        submit_data = {'submitOrderParam.sopNotPutInvoice': 'false',
                'submitOrderParam.trackID': track_id.attr.value}
        # url = 'http://trade.jd.com/order/isShowCheckCode.action'
        url = 'http://trade.jd.com/async/order/obtainOrderExt.action'
        ext_info = self.sn.post(url).json()
        print ext_info
        while True:
            if ext_info['showCheckCode']:
                ntype = ext_info['checkCodeType']
                rid = '{}{}'.format(random.random(), random.random())
                if ntype == 0:
                    check_url = 'http://trade.jd.com//order/getCheckCode.action?rid={}'.format(rid)
                elif ntype == 1:
                    check_url = checkCodeUrl="http://captcha.jd.com/verify/image?acid={}&srcid=trackWeb&is={}".format(rid, ext_info['encryptClientInfo'])
                else:
                    check_url = 'http://trade.jd.com//order/getCheckCode.action?rid={}'.format(rid)
                print check_url
                vcode = self.get_vcode(self.sn.get(check_url).content)
                submit_data['submitOrderParam.checkcodeTxt'] = vcode
                submit_data['submitOrderParam.checkCodeRid'] = rid
            url = 'http://trade.jd.com/order/submitOrder.action'
            res = self.sn.post(url, submit_data).json()
            print res
            if res['success']:
                print 'order ok'
                break
            else:
                if res['message'] and u'验证码不正确' in res['message']:
                    print u'验证码不正确'
                else:
                    print res
                    break

    def buy(self, sku):
        self.add_to_cart(sku)
        self.submit_order()

    def add_address(self, address):
        url = 'http://easybuy.jd.com/address/addAddress.action'
        res = self.sn.post(url, address)
        jd = PyQuery(res.text)('div')
        # 新加的地址在最前面，
        addr_id = jd.children().eq(1).attr.id
        if not addr_id: return
        addr_id = addr_id.split('-')[1]
        # 设置支付信息
        data = {'addressId': addr_id,
                'paymentId': '4',
                'pickId': '0',
                'pickName': ''}
        url = 'http://easybuy.jd.com/address/savePayment.action'
        res = self.sn.post(url, data)
        print res.text
        # 设置成默认的收货地址
        url = 'http://easybuy.jd.com/address/setAddressDefaultById.action'
        data = {'addressId': addr_id}
        res = self.sn.post(url, data)
        print res.text

def jd_register(name, pwd, get_vcode=get_vcode):
    url = 'https://reg.jd.com/reg/person?ReturnUrl=http%3A//www.jd.com/'
    sn = requests.Session()
    sn.headers = {'User-Agent':'Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1;; SIMBAR={E540A73C-FFAE-11E1-A7F7-002618241525})',
                             'x-requested-with':'XMLHttpRequest',
                             'Accept': 'application/json, text/javascript, */*; q=0.01',
                             }

    jd = PyQuery(sn.get(url).text)
    res = sn.get('https://reg.jd.com/validate/isPinEngaged?pin={}&r={}'.format(name, random.random()))
    print res.json()

    # get verify code
    vimg = jd('img#JD_Verification1')
    vurl = 'http:{}{}'.format(vimg.attr.onclick.split("'")[1], int(time.time()))
    authcode = get_vcode(sn.get(vurl).content)
    unknow_fd = jd('div#o-password').next('input')
    data = {'authcode': authcode,
            'mobileCode': '',
            unknow_fd.attr.name: unknow_fd.attr.value,
            'pwd': pwd,
            'pwdRepeat': pwd,
            'regName': name,
            'regType': 'person',
            'uuid': jd('input[name=uuid]').attr.value,
            'schoolid': ''}
    print data
    random.seed()
    reg_url = 'https://reg.jd.com/reg/regService?r={}&ReturnUrl=http%3A//www.jd.com/'.format(random.random())
    res = sn.post(url=reg_url, data=data)
    print res.text
    try:
        res = json.loads(res.text[1:-1])
        fn = 'ok.txt' if 'success' in res else 'fail.txt'
        if 'success' in res:
            with open('ok.txt', 'a') as fp:
                fp.write('{}={}\n'.format(name, pwd))
        if 'info' in res and res['info'] == u'您所使用的IP注册过于频繁，请稍后再试':
            print 'sleep for 3 minute...'
            time.sleep(180)
    except:
        pass


class TestJD(unittest.TestCase):

    def setUp(self):
        name = 'FKWzIS'
        pwd = 'QxG48HIv'
        self.user = JD(name, pwd)

    @unittest.skip('ok')
    def test_login(self):
        name = 'e5336bcf'
        pwd = '002618241525'
        res = JD(name, pwd)
        self.assertTrue('success' in res.status)
        name = '049af8cf'
        pwd = '123'
        res = JD(name, pwd)
        self.assertTrue('pwd' in res.status)
    @unittest.skip('ok')
    def test_subscribe(self):
        name = 'e871bf2e'
        pwd = '002618241525'
        user = JD(name, pwd)
        skuid = '1043963'
        user.subscribe(skuid)

    @unittest.skip('ok')
    def test_add_to_cart(self):
        skuid = '974077'
        self.user.add_to_cart(skuid)

    @unittest.skip('ok')
    def test_submit_order(self):
        self.user.submit_order()
#    @unittest.skip('ok')
    def test_buy(self):
        sku = '1028639002'
        self.user.buy(sku)
    @unittest.skip('ok')
    def test_address(self):
        address_info = {'addressInfoParam.addressAlias': '单位',
                        'addressInfoParam.cityId': 1016,
                        'addressInfoParam.consigneeAddress': '经济开发区',
                        'addressInfoParam.consigneeName': '张好',
                        'addressInfoParam.countyId': 2962,
                        'addressInfoParam.easyBuy': 0,
                        'addressInfoParam.email': '',
                        'addressInfoParam.fullAddress': '山东淄博市淄川区钟楼街道经济开发区',
                        'addressInfoParam.mobile': '13793321287',
                        'addressInfoParam.phone': '',
                        'addressInfoParam.provinceId': 13,
                        'addressInfoParam.townId': 47258,}
        self.user.add_address(address_info)

def batch_register():
    for i in range(0, 10000):
        name = random_string(6)
        pwd = random_string(8)
        jd_register(name, pwd)
        time.sleep(random.randint(1,3))
if __name__ == '__main__':
    unittest.main()

